home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / exec / addtask.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  5KB  |  199 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: addtask.c,v 1.6 1996/09/11 16:54:23 digulla Exp $
  4.     $Log: addtask.c,v $
  5.     Revision 1.6  1996/09/11 16:54:23  digulla
  6.     Always use __AROS_SLIB_ENTRY() to access shared external symbols, because
  7.         some systems name an external symbol "x" as "_x" and others as "x".
  8.         (The problem arises with assembler symbols which might differ)
  9.  
  10.     Revision 1.5  1996/08/16 14:05:12  digulla
  11.     Added debug output
  12.  
  13.     Revision 1.4  1996/08/13 13:55:57  digulla
  14.     Replaced __AROS_LA by __AROS_LHA
  15.     Replaced some __AROS_LH*I by __AROS_LH*
  16.     Sorted and added includes
  17.  
  18.     Revision 1.3  1996/08/01 17:41:03  digulla
  19.     Added standard header for all files
  20.  
  21.     Desc:
  22.     Lang: english
  23. */
  24. #include <exec/execbase.h>
  25. #include <aros/libcall.h>
  26. #include "machine.h"
  27.  
  28. #include "exec_debug.h"
  29. #ifndef DEBUG_AddTask
  30. #   define DEBUG_AddTask 0
  31. #endif
  32. #if DEBUG_AddTask
  33. #   undef DEBUG
  34. #   define DEBUG 1
  35. #endif
  36. #include <aros/debug.h>
  37.  
  38. static void KillCurrentTask(void);
  39. void __AROS_SLIB_ENTRY(TrapHandler,Exec)(void);
  40.  
  41. /*****************************************************************************
  42.  
  43.     NAME */
  44.     #include <clib/exec_protos.h>
  45.  
  46.     __AROS_LH3(APTR, AddTask,
  47.  
  48. /*  SYNOPSIS */
  49.     __AROS_LHA(struct Task *,     task,      A1),
  50.     __AROS_LHA(APTR,              initialPC, A2),
  51.     __AROS_LHA(APTR,              finalPC,   A3),
  52.  
  53. /*  LOCATION */
  54.     struct ExecBase *, SysBase, 47, Exec)
  55.  
  56. /*  FUNCTION
  57.     Add a new task to the system. If the new task has the highest
  58.     priority of all and task switches are allowed it will be started
  59.     immediately.
  60.     Certain task fields should be intitialized and a stack must be
  61.     allocated before calling this function. tc_SPReg will be used as the
  62.     starting location for the stack pointer, i.e. a part of the stack can
  63.     be reserved to pass the task some initial arguments.
  64.     Memory can be added to the tc_MemEntry list and will be freed when the
  65.     task dies. The new task's registers are set to 0.
  66.  
  67.     INPUTS
  68.     task      - Pointer to task structure.
  69.     initialPC - Entry point for the new task.
  70.     finalPC   - Routine that is called if the initialPC() function returns.
  71.             A NULL pointer installs the default finalizer.
  72.  
  73.     RESULT
  74.     The address of the new task or NULL if the operation failed (can only
  75.     happen with TF_ETASK set - currenty not implemented).
  76.  
  77.     NOTES
  78.  
  79.     EXAMPLE
  80.  
  81.     BUGS
  82.  
  83.     SEE ALSO
  84.     RemTask()
  85.  
  86.     INTERNALS
  87.  
  88.     HISTORY
  89.  
  90. ******************************************************************************/
  91. {
  92.     __AROS_FUNC_INIT
  93.     APTR sp;
  94.  
  95.     D(bug("Call AddTask (%08lx (\"%s\"), %08lx, %08lx)\n"
  96.     , task
  97.     , task->tc_Node.ln_Name
  98.     , initialPC
  99.     , finalPC
  100.     ));
  101.  
  102.     /* Set node type to NT_TASK if not set to something else. */
  103.     if(!task->tc_Node.ln_Type)
  104.     task->tc_Node.ln_Type=NT_TASK;
  105.  
  106.     /* Sigh - you should provide a name for your task. */
  107.     if(task->tc_Node.ln_Name==NULL)
  108.     task->tc_Node.ln_Name="unknown task";
  109.  
  110.     /* This is moved into SysBase at the tasks's startup */
  111.     task->tc_IDNestCnt=-1;
  112.  
  113.     /* Signals default to all system signals allocated. */
  114.     if(task->tc_SigAlloc==0)
  115.     task->tc_SigAlloc=0xffff;
  116.  
  117.     /* Currently only used for segmentation violation */
  118.     if(task->tc_TrapCode==NULL)
  119.     task->tc_TrapCode=&__AROS_SLIB_ENTRY(TrapHandler,Exec);
  120.  
  121.     /* Get new stackpointer. */
  122.     sp=task->tc_SPReg;
  123.     if(task->tc_SPReg==NULL)
  124. #if STACK_GROWS_DOWNWARDS
  125.     sp=(UBYTE *)task->tc_SPUpper-SP_OFFSET;
  126. #else
  127.     sp=(UBYTE *)task->tc_SPLower-SP_OFFSET;
  128. #endif
  129.  
  130.     /* Default finalizer? */
  131.     if(finalPC==NULL)
  132.     finalPC=&KillCurrentTask;
  133.  
  134.     /* Init new context. */
  135.     sp=PrepareContext(sp,initialPC,finalPC);
  136.  
  137.     /* store sp */
  138.     task->tc_SPReg=sp;
  139.  
  140.     /* Set the task flags for switch and launch. */
  141.     if(task->tc_Switch)
  142.     task->tc_Flags|=TF_SWITCH;
  143.  
  144.     if(task->tc_Launch)
  145.     task->tc_Flags|=TF_LAUNCH;
  146.  
  147.     /* tc_MemEntry _must_ already be set. */
  148.  
  149.     /*
  150.     Protect the task lists. This must be done with Disable() because
  151.     of Signal() which is usable from interrupts and may change those
  152.     lists.
  153.      */
  154.     Disable();
  155.  
  156.     /* Add the new task to the ready list. */
  157.     task->tc_State=TS_READY;
  158.     Enqueue(&SysBase->TaskReady,&task->tc_Node);
  159.  
  160.     /*
  161.     Determine if a task switch is necessary. (If the new task has a
  162.     higher priority than the current one and the current one
  163.     is still active.) If the current task isn't of type TS_RUN it
  164.     is already gone.
  165.     */
  166.     if(task->tc_Node.ln_Pri>SysBase->ThisTask->tc_Node.ln_Pri&&
  167.        SysBase->ThisTask->tc_State==TS_RUN)
  168.     {
  169.     /* Are taskswitches allowed? (Don't count own Disable() here) */
  170.     if(SysBase->TDNestCnt>=0||SysBase->IDNestCnt>0)
  171.         /* No. Store it for later. */
  172.         SysBase->AttnResched|=0x80;
  173.     else
  174.     {
  175.         /* Switches are allowed. Move the current task away. */
  176.         SysBase->ThisTask->tc_State=TS_READY;
  177.         Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  178.  
  179.         /* And force a rescedule. */
  180.         Switch();
  181.     }
  182.     }
  183.  
  184.     Enable();
  185.  
  186.     ReturnPtr ("AddTask", struct Task *, task);
  187.     __AROS_FUNC_EXIT
  188. } /* AddTask */
  189.  
  190. /* Default finalizer. */
  191. static void KillCurrentTask(void)
  192. {
  193.     /* I need the global SysBase variable here - there's no local way to get it. */
  194.     extern struct ExecBase *SysBase;
  195.  
  196.     /* Get rid of current task. */
  197.     RemTask(SysBase->ThisTask);
  198. }
  199.